/**
 * 
 */
package com.bn.feeds.tools;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.bn.feedMaster.FeedProcessException;
import com.bn.feeds.MasterFeedConfiguration;
import com.bn.feeds.utils.FeedConstants;

import atg.core.util.StringUtils;
import atg.nucleus.GenericService;
import atg.repository.MutableRepository;
import atg.repository.MutableRepositoryItem;
import atg.repository.Repository;
import atg.repository.RepositoryException;
import atg.repository.RepositoryItem;

// TODO: Auto-generated Javadoc
/**
 * The Class RepositoryTools.
 */
public class RepositoryTools extends GenericService implements FeedRepositoryTool {

    /**
	 * Populate mandatory properties.
	 * 
	 * @param mutableItem
	 *            the mutable item
	 * @param repositoryPropertiesToTokenIndexMap
	 *            the repository properties to token index map
	 * @param propDataTypeMap
	 *            the prop data type map
	 * @param mandatoryPropeties
	 *            the mandatory propeties
	 * @param defaulProperty
	 *            the defaul property
	 * @param itemList
	 *            the item list
	 * @throws NumberFormatException
	 *             the number format exception
	 * @throws ParseException
	 *             the parse exception
	 */
    protected void populateMandatoryProperties(MutableRepositoryItem mutableItem,
            Map<String, Integer> repositoryPropertiesToTokenIndexMap, Map<String, String> propDataTypeMap,
            List<String> mandatoryPropeties, String defaulProperty, String[] itemList) throws NumberFormatException, ParseException {

        if ((mutableItem != null) && ((mandatoryPropeties != null) && (!mandatoryPropeties.isEmpty()))
                && (!StringUtils.isEmpty(defaulProperty))) {
            for (String mandatoryPropety: mandatoryPropeties){
                mutableItem.setPropertyValue(mandatoryPropety,
                                             getValue(itemList[repositoryPropertiesToTokenIndexMap.get(defaulProperty)],propDataTypeMap.get(mandatoryPropety)));
            }
        } 
        
    }

    /**
	 * Gets the value.
	 * 
	 * @param value
	 *            the value
	 * @param dataType
	 *            the data type
	 * @return the value
	 * @throws NumberFormatException
	 *             the number format exception
	 * @throws ParseException
	 *             the parse exception
	 */
    protected Object getValue(String value, String dataType) throws NumberFormatException, ParseException{
        Object convertedValue = null;
        
        if (StringUtils.isBlank(dataType)){
            convertedValue = value;
        } else if (StringUtils.isBlank(value)){
            convertedValue =  null;
        } else if (dataType.equalsIgnoreCase("int") || dataType.equalsIgnoreCase("integer")) {
            convertedValue = Integer.parseInt(value);
        } else if (dataType.equalsIgnoreCase("double")) {
            convertedValue = Double.parseDouble(value);
        } else if (dataType.equalsIgnoreCase("long")) {
            convertedValue = Long.parseLong(value);
        } else if (dataType.equalsIgnoreCase("Boolean")) {
            if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("1")
                || value.equalsIgnoreCase("y")) {
                // convertedValue=new Boolean(true);
                convertedValue = Boolean.TRUE;
            } else {
                convertedValue = Boolean.FALSE;
            }
        } else if (dataType.equalsIgnoreCase("Date")) {
            SimpleDateFormat sdf = new SimpleDateFormat(FeedConstants.DATE_FORMAT);
            convertedValue = sdf.parse(value);
        } else {
            convertedValue = value;
        }

        return convertedValue;
    }

    /**
	 * Clean up all the item descriptors of a given type from repository.
	 * 
	 * @param repository
	 *            the repository
	 * @param itemDescriptor
	 *            the item descriptor
	 * @return true, if successful
	 * @throws FeedProcessException
	 *             the feed process exception
	 */
    @Override
    public boolean cleanUpData(MutableRepository repository, String itemDescriptor) throws FeedProcessException {
        
        return false;
    }

    /**
	 * Adds/updates a repository item with the data provided
	 * 
	 * @param config
	 *            configuration for the Feed
	 * @param itemList
	 *            one Row data
	 * @param header
	 *            the feed file header
	 * @param idColumnIndex
	 *            index of id column property in data row(itemList)
	 * @param repositoryPropertiesToTokenIndexMap
	 *            a map which contains repository properties(primitive type) index in data row(which property has value at what index in data row)
	 * @param repositoryItemPropertiesToTokenIndexMap
	 *            a map which contains repository properties(RepositoryItem type) index in data row(which property has value at what index in data row)
	 * @param productProcessedMap
	 *            a map which contains id's of all the items which are processed so far in the feed execution
     * @return 
	 * @throws FeedProcessException
	 *             the feed process exception
	 */
    public List<String> processRecord(MasterFeedConfiguration config, 
            String[] itemList, String[] header, int idColumnIndex, 
            Map<String, Integer> repositoryPropertiesToTokenIndexMap,
            Map<String, Integer> repositoryItemPropertiesToTokenIndexMap,Map<String, String> productProcessedMap, Map<String, Integer> mandatoryPropertiesMap)
            throws FeedProcessException {
        if (isLoggingDebug()) { 
            logDebug("Entering repositorytools .RepositoryTools processRecord() ....");
        }
        List<String> errorList = new ArrayList<String>();
        if(!validateMandatoryProperties(config, mandatoryPropertiesMap, itemList, errorList)){
            return errorList;
            }
        try {
            String repositoryId = "";
            MutableRepository mutableRespository =  config.getRepository();
            Repository repository = config.getPrdRepository();
            String itemDescriptor = config.getItemDescriptorName();
            Map<String, String> propertyMappings = config.getTokenPropertyMap();
            Map<String, String> propDataTypeMap = config.getPropDataTypeMap();
            List<String> mandatoryPropeties = config.getMandatoryProperties();
            String defaulProperty = config.getDefaultProperty();
            MutableRepositoryItem mutableItem = null;
            boolean isCreated = false;
            
            if (config.isUseOOTBId()){
                isCreated = true;
                mutableItem = ((MutableRepository) mutableRespository).createItem(itemDescriptor);
            } else {
                repositoryId = itemList[idColumnIndex];
                if(!StringUtils.isBlank(repositoryId)){
                	repositoryId=repositoryId.trim();
                	  RepositoryItem repoItem = repository.getItem(repositoryId, itemDescriptor);
                      
                      if (repoItem != null) {
                           mutableItem = mutableRespository.getItemForUpdate(repositoryId, itemDescriptor);
                       } else {
                           isCreated = true;
                           mutableItem = ((MutableRepository) mutableRespository).createItem(repositoryId, itemDescriptor);
                           
                       }
                }else{

                    if(isLoggingDebug()){
                        logDebug("CouponRepositoryTools::>processRecord()::Value of Id property in feed is null");
                    }
                    throw new FeedProcessException("Value of Id property in feed is null");
                }
              
            }
            for (int index = 0; index < header.length; index++) {
                if (index != idColumnIndex) {
                    mutableItem.setPropertyValue(propertyMappings.get(header[index]),
                                                 getValue(itemList[index],propDataTypeMap.get(propertyMappings.get(header[index]))));
                }
            }
            
            populateMandatoryProperties(mutableItem, repositoryPropertiesToTokenIndexMap, propDataTypeMap, mandatoryPropeties, defaulProperty, itemList);
    
            if (isCreated){
                mutableRespository.addItem(mutableItem);
            } else {
                mutableRespository.updateItem(mutableItem);
            }
        } catch(RepositoryException e){
            throw new FeedProcessException(e);
        }  catch(NumberFormatException e){
            throw new FeedProcessException(e);
        } catch(ParseException e){
            throw new FeedProcessException(e);
        }
        if (isLoggingDebug()) {
            logDebug("Exiting repositorytools .RepositoryTools processRecord() ....");
        }
        return errorList;
    }
    
    protected boolean validateMandatoryProperties(MasterFeedConfiguration config,Map<String, Integer> mandatoryPropertiesMap, String[] dataRow, List<String> errorList) {
        String mandtryPropertyValue = null;
        List<String> mandatoryProperties = null;
        mandatoryProperties = config.getMandatoryProperties();
        ArrayList<String> mandatoryErrorList = new ArrayList<String>();
       if(mandatoryProperties!=null && !mandatoryProperties.isEmpty()){
          for(String mandatoryProperty : mandatoryProperties){
              if(mandatoryPropertiesMap.get(mandatoryProperty)!=null){
                  mandtryPropertyValue = dataRow[mandatoryPropertiesMap.get(mandatoryProperty)];
                  if(StringUtils.isBlank(mandtryPropertyValue)){
                      mandatoryErrorList.add(mandatoryProperty);
                  }
              }else{
                  mandatoryErrorList.add(mandatoryProperty);
              }
            }   
       }
       if(mandatoryErrorList.size()>0){
           if(isLoggingError()){
               logError("Value missing in Feed for Mandatory properties:" + mandatoryErrorList.toString()+" for row: "+Arrays.toString(dataRow));
           }
           errorList.add("Value missing in Feed for Mandatory properties:" + mandatoryErrorList.toString()+" for row: "+Arrays.toString(dataRow));
           return false;
           }
       return true;
    }
}
